package org.tigris.atlas.examples.persist;

import java.util.Iterator;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.tigris.atlas.examples.service.delegate.EntityMaintenanceServiceDelegate;
import org.tigris.atlas.examples.service.delegate.ServiceDelegateFactory;
import org.tigris.atlas.examples.transfer.DomainWithReference;
import org.tigris.atlas.examples.transfer.DomainWithReferencePK;
import org.tigris.atlas.examples.transfer.SimpleReferencedDomain;
import org.tigris.atlas.examples.transfer.SimpleReferencedDomainPK;
import org.tigris.atlas.examples.transfer.TransferObjectFactory;
import org.tigris.atlas.messages.Message;
import org.tigris.atlas.messages.Messages;
import org.tigris.atlas.service.ServiceResponse;

public class TestDomainWithReferenceDao extends TestCase {
	
	private static Log log = LogFactory.getLog(TestDomainWithReferenceDao.class); 

	DomainWithReferencePK pk;
	String srd1id;
	String srd2id;
	String dwr1id;
	String dwr2id;
	String dwr3id;
	EntityMaintenanceServiceDelegate delegate;

	protected void setUp() throws Exception {
		super.setUp();
		
		pk = (DomainWithReferencePK) TransferObjectFactory.createDomainWithReferencePK();
		delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		
		SimpleReferencedDomain srd1 = TransferObjectFactory.createSimpleReferencedDomain();
		srd1.setName( "Name1" );
		srd1 = delegate.save( srd1 ).getSimpleReferencedDomain();
		srd1id = srd1.getId();
		
		SimpleReferencedDomain srd2 = TransferObjectFactory.createSimpleReferencedDomain();
		srd2.setName( "Name2" );
		srd2 = delegate.save( srd2 ).getSimpleReferencedDomain();
		srd2id = srd2.getId();
	
		DomainWithReference dwr1 = TransferObjectFactory.createDomainWithReference();
		dwr1.setSimpleReferencedDomain( srd1 );
		dwr1 = delegate.save( dwr1 ).getDomainWithReference();
		dwr1id = dwr1.getId();
	
		DomainWithReference dwr2 = TransferObjectFactory.createDomainWithReference();
		dwr2.setSimpleReferencedDomain( srd2 );
		dwr2 = delegate.save( dwr2 ).getDomainWithReference();
		dwr2id = dwr2.getId();
	
		DomainWithReference dwr3 = TransferObjectFactory.createDomainWithReference();
		dwr3.setSimpleReferencedDomain( null );
		dwr3 = delegate.save( dwr3 ).getDomainWithReference();
		dwr3id = dwr3.getId();
	}

	protected void tearDown() throws Exception {		
		EntityMaintenanceServiceDelegate delegate = ServiceDelegateFactory.createEntityMaintenanceServiceDelegate();
		
		ServiceResponse response;		
		DomainWithReferencePK dwrpk = TransferObjectFactory.createDomainWithReferencePK();
		dwrpk.setId( dwr1id );
		response = delegate.delete( dwrpk );
		checkResponseForErrors(response);
		
		dwrpk.setId( dwr2id );
		response = delegate.delete( dwrpk );
		checkResponseForErrors(response);
		
		dwrpk.setId( dwr3id );
		response = delegate.delete( dwrpk );
		checkResponseForErrors(response);
		
		SimpleReferencedDomainPK srdpk = TransferObjectFactory.createSimpleReferencedDomainPK();
		srdpk.setId( srd1id );
		response = delegate.delete( srdpk );
		checkResponseForErrors(response);
		
		srdpk.setId( srd2id );
		response = delegate.delete( srdpk );
		checkResponseForErrors(response);		
		
		dwr1id = null;
		dwr2id = null;
		dwr3id = null;
		srd1id = null;
		srd2id = null;

		super.tearDown();
	}
	
	private boolean checkResponseForErrors(ServiceResponse response) {
		boolean hasErrors = false;
		
		if (response != null) {
			Messages messages = response.getMessages();
			if (messages.hasErrorMessages()) {
				hasErrors = true;
				
				Iterator i = messages.getErrorMessages().iterator();
				while (i.hasNext()) {
					log.error(((Message)i.next()).toString());
					
				}
			}
		}
		
		return hasErrors;
	}

	public void testFindObjectWithReference() {
		pk.setId(dwr1id);
		DomainWithReference domain = delegate.findByPrimaryKey(pk).getDomainWithReference();
		assertNotNull(domain);

		SimpleReferencedDomain refdDomain = domain.getSimpleReferencedDomain();
		assertNotNull(refdDomain);
		assertEquals(srd1id, refdDomain.getId());
		assertEquals("Name1", refdDomain.getName());
	}

	public void testFindObjectWithoutReference() {
		pk.setId(dwr3id);
		DomainWithReference domain = delegate.findByPrimaryKey(pk).getDomainWithReference();
		assertNotNull(domain);
		assertNull(domain.getSimpleReferencedDomain());
	}

	public void testCreateWithValidReference() {
		SimpleReferencedDomainPK refPk = TransferObjectFactory.createSimpleReferencedDomainPK();
		refPk.setId(srd1id);
		SimpleReferencedDomain refdDomain = delegate.findByPrimaryKey(refPk).getSimpleReferencedDomain();
		
		DomainWithReference domain = TransferObjectFactory.createDomainWithReference();
		domain.setSimpleReferencedDomain(refdDomain);

		domain = delegate.save(domain).getDomainWithReference();
		assertNotNull(domain);
		assertNotNull(domain.getId());
		assertFalse(domain.getMessages().hasErrorMessages());

		pk.setId(domain.getId());
		domain = delegate.findByPrimaryKey(pk).getDomainWithReference();
		refdDomain = domain.getSimpleReferencedDomain();
		assertNotNull(refdDomain);
		assertEquals(srd1id, refdDomain.getId());
		assertEquals("Name1", refdDomain.getName());
		
		delegate.delete(domain.getDomainWithReferencePK());
	}
	
	public void testCreateWithNoReference() {
		DomainWithReference domain = TransferObjectFactory.createDomainWithReference();
		
		domain = delegate.save(domain).getDomainWithReference();
		assertNotNull(domain);
		assertNotNull(domain.getId());
		assertNull(domain.getSimpleReferencedDomain());
		assertFalse(domain.getMessages().hasErrorMessages());
	}
	
	public void testReferenceUnchanged() {	
		SimpleReferencedDomainPK refPk = TransferObjectFactory.createSimpleReferencedDomainPK();
		refPk.setId(srd1id);
		SimpleReferencedDomain refdDomain = delegate.findByPrimaryKey(refPk).getSimpleReferencedDomain();
		refdDomain.setName("invalidChangeToReference");
		
		DomainWithReference domain = TransferObjectFactory.createDomainWithReference();
		domain.setSimpleReferencedDomain(refdDomain);

		domain = delegate.save(domain).getDomainWithReference();
		assertNotNull(domain);
		assertNotNull(domain.getId());
		assertFalse(domain.getMessages().hasErrorMessages());

		pk.setId(domain.getId());
		domain = delegate.findByPrimaryKey(pk).getDomainWithReference();
		refdDomain = domain.getSimpleReferencedDomain();
		assertNotNull(refdDomain);
		assertEquals(srd1id, refdDomain.getId());
		assertEquals("Name1", refdDomain.getName());
		
		delegate.delete(domain.getDomainWithReferencePK());
	}

}
